import { useEffect, useRef, useState } from 'react';
import { Button, Form, Input, Modal, Upload, UploadFile, Image, Cascader, Radio, InputNumber, message } from 'antd';
import { useModel, styled, Access } from '@umijs/max'
import { saveZhaoMu, getZhaoMuInfo, PowerStatus, LockStatus, ZhaoMuStatus } from './services'
import { useRequest } from 'ahooks';
import { SUCCESS_CODE } from '@/constants';
import { PlusOutlined } from '@ant-design/icons';
import { fileUp, queryCityOptions2 } from '@/services/common';
import { geocoder, searchRegion, StationParkType } from '@/pages/station/stationList/services';
import useTencentMap from '@/components/useTencentMap';
import OpeningHours from '@/pages/station/stationList/components/OpeningHours';
import { enum2options } from '@/utils/enum2options';
import ManagerInfo from './ManagerInfo';
import dayjs, { Dayjs } from 'dayjs';
import { Editor, Toolbar } from '@wangeditor/editor-for-react'
import { IDomEditor, IEditorConfig, IToolbarConfig } from '@wangeditor/editor'

const MapContainer = styled.div`
  width: 100%;
  height: 240px;
  display: flex;
  gap: 16px;

  .map-content {
    width: 740px;
    height: 100%;
    border-radius: 6px;
    flex-shrink: 0;
    overflow: hidden;
  }

  .map-list {
    flex: 1;
    height: 100%;
    overflow-y: auto;
    border: 1px solid #bbbbbb;
    border-radius: 6px;
    padding: 8px 12px;
    display: flex;
    flex-direction: column;
    gap: 8px;

    .map-item {
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
      cursor: pointer;
      padding: 6px 10px;
      border: 1px solid #eee;
      border-radius: 6px;
      flex-shrink: 0;
    }
  }
`

const LatLngContainer = styled.div`
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;

  .label {
    height: var(--ant-form-label-height);
    color: var(--ant-form-label-color);
    font-size: var(--ant-form-label-font-size);
    display: flex;
    align-items: center;
    margin-left: 16px;

    &::before {
      content: '*';
      color: var(--ant-form-label-required-mark-color);
      font-size: var(--ant-font-size);
      font-family: SimSun,sans-serif;
      padding-right: 4px;
    }

    &::after {
      content: ':';
      padding-left: 2px;
      padding-right: 8px;
    }
  }
`

let markerClick = false

type InsertFnType = (url: string, alt?: string, href?: string) => void

type WxSearchResult = {
  address: string
  location: {
    lat: number
    lng: number
  }
}

const managerInfoValidator = (value: Record<string, string>) => {
  const keys = Object.keys(value || {})
  if (keys.length && !keys.at(-1)?.endsWith('23:59')) {
    return Promise.reject(new Error('尚有剩余可分配时间，请继续添加联系方式'))
  }
  return Promise.resolve()
}

function parseHtmlToTree(htmlString: string): string {
  // 使用DOMParser解析HTML字符串
  const parser = new DOMParser();
  const doc = parser.parseFromString(htmlString, 'text/html');

  // 定义一个递归函数来构建树状结构数组
  function buildTree(node: any) {
      if (node.nodeType === Node.ELEMENT_NODE) {
          // 构建元素对象
          const element: any = {
              tag: node.tagName.toLowerCase(),
              attributes: {},
              children: []
          };

          // 获取所有属性
          for (let i = 0; i < node.attributes.length; i++) {
              const attr = node.attributes[i];
              element.attributes[attr.name] = attr.value;
          }

          // 遍历子节点
          let currentTextNode = '';
          for (let childNode = node.firstChild; childNode; childNode = childNode.nextSibling) {
              if (childNode.nodeType === Node.TEXT_NODE) {
                  // 如果是文本节点，累积文本
                  currentTextNode += childNode.textContent.trim();
              } else {
                  // 如果是元素节点，则处理累积的文本并重置
                  if (currentTextNode !== '') {
                      element.children.push({
                          tag: 'text',
                          content: currentTextNode
                      });
                      currentTextNode = '';
                  }
                  // 处理子元素
                  const childData = buildTree(childNode);
                  if (childData) {
                      element.children.push(childData);
                  }
              }
          }
          // 处理最后一个累积的文本
          if (currentTextNode !== '') {
              element.children.push({
                  tag: 'text',
                  content: currentTextNode
              });
          }

          return element;
      } else if (node.nodeType === Node.TEXT_NODE) {
          // 返回文本节点的值
          return node.textContent.trim();
      }
  }

  // 从body节点开始构建树状结构
  const body = doc.body;
  return JSON.stringify(buildTree(body));
}

const RoleEditPage: React.FC<RoutePageProps> = (props) => {
  const [editForm] = Form.useForm()
  const { runAsync, loading } = useRequest(saveZhaoMu, {manual: true})
  const { data: stationInfo, runAsync: getData } = useRequest(getZhaoMuInfo, {manual: true})
  const cityOptions = useRequest(queryCityOptions2)
  const { closeCurrentTab } = useModel('global')
  const [imgList, setImgList] = useState<string[]>([])
  const [previewCurrent, setPreviewCurrent] = useState(0)
  const imageList = Form.useWatch('imgs', editForm)
  const [cityName, setCityName] = useState<string>()
  const keyword = useRef<string>('')
  const tencentReq = useRequest(searchRegion, {manual: true, debounceWait: 200})
  const [addressList, setAddressList] = useState<WxSearchResult[]>([])
  const marker = useRef<any>()
  const tencentMap = useTencentMap('mapContainerZm')
  const getGeocoder = useRequest(geocoder, {manual: true})
  const [editor, setEditor] = useState<IDomEditor | null>(null)
  const [disposeRes, setDisposeRes] = useState<string>('')

  const toolbarConfig: Partial<IToolbarConfig> = {
    toolbarKeys: ['bold', 'underline', 'italic', 'through', 'clearStyle', 'color', 'fontSize', 'uploadImage'],
  }
  const editorConfig: Partial<IEditorConfig> = {
    placeholder: '请输入材料...',
    MENU_CONF: {
      uploadImage: {
        server: 'custom',
        // 自定义上传
        async customUpload(file: File, insertFn: InsertFnType) {
          const _formData = new FormData()
          _formData.append('type', '2')
          _formData.append('file', file)
          fileUp(_formData).then(res => {
            insertFn(res.data)
          })
        }
      },
    },
  }

  const normFile = (e: any) => {
    if (Array.isArray(e)) {
      return e;
    }
    return e?.fileList;
  }

  const onFileUpLoadChange = (file: UploadFile) => {
    const { status, response, uid } = file
    if (status === 'done' && response) {
      const imgs = editForm.getFieldValue('imgs')
      const { code, data, text } = response
      if (code === SUCCESS_CODE) {
        editForm.setFieldsValue({
          imgs: imgs.map((item: any) => {
            if (item.uid === uid) return {
              status: 'done', url: data
            }
            return item
          })
        })
      } else {
        Modal.error({
          title: '错误',
          content: text === '上传文件过大' ? '文件体积超过 2M，请重新上传' : '图片上传失败，请重试',
        })
        editForm.setFieldsValue({
          imgs: imgs.filter((item: any) => item.uid !== uid)
        })
      }
    } else if (status === 'error') {
      const imgs = editForm.getFieldValue('imgs')
      editForm.setFieldsValue({
        imgs: imgs.filter((item: any) => item.uid !== uid)
      })
    }
  }

  const openPreview = (file: UploadFile) => {
    const index = imageList.findIndex((item: UploadFile) => item.uid === file.uid)
    setPreviewCurrent(index)
    setImgList(imageList.map((item: UploadFile) => item.url!))
  }

  const onCityChange = (value: any, item: any) => {
    if (item.length) {
      setCityName(item[2].label)
    }
  }

  const onSearch = () => {
    if (!cityName) {
      Modal.warn({
        title: '提示',
        content: '请先选择所在城市',
      })
      return
    }
    if (!keyword.current) {
      Modal.warn({
        title: '提示',
        content: '请输入要搜索的地址',
      })
      return
    }
    tencentReq.runAsync({
      title: keyword.current,
      cityId: cityName,
    }).then((res: any) => {
      const result = JSON.parse(res.data)
      if (result.status === 0) {
        if (result.data.length) {
          setAddressList(result.data)
        } else {
          Modal.warn({
            content: '未查询到相关地址',
          })
        }
      } else {
        Modal.error({
          title: '错误',
          content: result.message,
        })
      }
    })
  }

  const reSetMapMarker = (options: {position: {lat: number, lng: number}, properties: Record<string, string>}[]) => {
    marker.current.setGeometries(options)
    tencentMap.setCenter(new window.TMap.LatLng(options[0].position.lat, options[0].position.lng))
  }

  const onAddressChose = (address: WxSearchResult) => {
    editForm.setFieldsValue({
      longitude: address.location.lng,
      latitude: address.location.lat,
      address: address.address,
    })
    reSetMapMarker([{
      position: new window.TMap.LatLng(address.location.lat, address.location.lng),
      properties: {
        address: address.address,
      }
    }])
  }

  const onFinish = (formValues: any) => {
    if (editor?.isEmpty()) {
      message.error('请输入场站介绍')
      return
    }
    const imgs = formValues.imgs.filter((item: any) => item.status === 'done').map((item: any) => item.url).join(',')
    const serviceInfo = formValues.serviceInfo.map((item: [Dayjs, Dayjs]) => {
      const [startTime, endTime] = item
      return `${startTime.format('HH:mm')}-${endTime.format('HH:mm')}`
    }).join(',')
    const _linkInfo = {
      linkInfo: formValues.linkInfo,
      scale: formValues.scale,
      hzqx: formValues.hzqx,
    }
    const _introInfo = `${disposeRes}__&&&&__${parseHtmlToTree(disposeRes)}`
    runAsync({
      ...formValues,
      imgs,
      cityId: formValues.cascader[2],
      cascader: undefined,
      serviceInfo: serviceInfo,
      linkInfo: JSON.stringify(_linkInfo),
      introInfo: _introInfo,
    })
    .then(() => {
      const event = new CustomEvent('refreshZhaoMuList')
      window.dispatchEvent(event)
      closeCurrentTab('/zhaoMu')
    })
  }

  useEffect(() => {
    if (stationInfo && tencentMap && marker.current) {
      const data = stationInfo.data
      reSetMapMarker([{
        position: new window.TMap.LatLng(data.latitude, data.longitude),
        properties: {
          address: data.address,
        }
      }])
      tencentMap.setCenter(new window.TMap.LatLng(data.latitude, data.longitude))
    }
  }, [stationInfo, marker.current])

  useEffect(() => {
    if (tencentMap) {
      // 注册地图点击事件
      tencentMap.on('click', (res: any) => {
        if (markerClick) {
          markerClick = false
          return
        }
        getGeocoder.runAsync({
          locX: res.latLng.lng,
          locY: res.latLng.lat,
        }).then((_res: any) => {
          const result = JSON.parse(_res.data)
          if (result.status === 0) {
            editForm.setFieldsValue({
              longitude: result.result.location.lng,
              latitude: result.result.location.lat,
              address: result.result.address,
            })
            reSetMapMarker([{
              position: new window.TMap.LatLng(res.latLng.lat, res.latLng.lng),
              properties: {
                address: result.result.address
              }
            }])
          } else {
            Modal.error({
              title: '错误',
              content: result.message,
            })
          }
        })
      })
      // 创建一个位于地图中心点的marker
			marker.current = new window.TMap.MultiMarker({
				map: tencentMap,
				geometries: [],
			})
      const center = tencentMap.getCenter()
      reSetMapMarker([{
        position: new window.TMap.LatLng(center.lat, center.lng),
        properties: {
          address: ''
        }
      }])
    }
  }, [tencentMap])

  useEffect(() => {
    const { id } = props.params
    if (id) {
      getData({stationId: id})
      .then(res => {
        const { data } = res
        const cascaderValue = [`${data.cityId.substring(0, 2)}0000`, `${data.cityId.substring(0, 4)}00`, data.cityId]
        const _linkInfo = data.linkInfo ? JSON.parse(data.linkInfo) : {}
        const _serviceInfo = []
        const serviceTimes = data.serviceInfo?.split(',') || []
        if (serviceTimes.length < 1 || !serviceTimes[0].includes('-')) {
          _serviceInfo.push([dayjs().set('hour', 0).set('minute', 0), dayjs().set('hour', 23).set('minute', 59)])
        } else {
          serviceTimes.forEach(item => {
            const times = item.split('-')
            _serviceInfo.push([dayjs(times[0], 'HH:mm'), dayjs(times[1], 'HH:mm')])
          })
        }
        editForm.setFieldsValue({
          id: data.id,
          stationName: data.stationName,
          longitude: data.longitude,
          latitude: data.latitude,
          cascader: cascaderValue,
          address: data.address,
          houseName: data.houseName,
          powerStatus: data.powerStatus,
          placeArea: data.placeArea,
          stubOneNum: data.stubOneNum,
          stubTwoNum: data.stubTwoNum,
          lockStatus: data.lockStatus,
          chargeNum: data.chargeNum,
          serviceInfo: _serviceInfo,
          infoMoney: data.infoMoney,
          status: data.status,
          notice: data.notice,
          parkType: data.parkType,
          parkInfo: data.parkInfo,
          imgs: data.imgs.split(',').map(it => ({status: 'done', url: it})),
          ground: data.ground,
          scale: _linkInfo.scale,
          hzqx: _linkInfo.hzqx,
          linkInfo: _linkInfo.linkInfo,
        })
        setDisposeRes(data.introInfo.split('__&&&&__')[0])
      })
    } else {
      editForm.setFieldsValue({
        id: undefined,
        stationName: undefined,
        longitude: undefined,
        latitude: undefined,
        cityId: undefined,
        address: undefined,
        houseName: undefined,
        powerStatus: undefined,
        placeArea: undefined,
        stubOneNum: undefined,
        stubTwoNum: undefined,
        lockStatus: undefined,
        chargeNum: undefined,
        serviceInfo: [[dayjs().set('hour', 0).set('minute', 0), dayjs().set('hour', 23).set('minute', 59)]],
        infoMoney: undefined,
        status: undefined,
        notice: undefined,
        parkType: undefined,
        parkInfo: undefined,
        imgs: undefined,
        ground: undefined,
        scale: undefined,
        hzqx: undefined,
        linkInfo: undefined,
      })
      setDisposeRes('')
    }
  }, [props.params.id])
  
  return (
    <div className='container'>
      <div className="card">
        <Form form={editForm} name='editZhaoMuForm' labelCol={{flex: '120px'}} onFinish={onFinish}>
          <Form.Item name='id' noStyle>
            <Input placeholder='请输入' style={{width: 320}} hidden />
          </Form.Item>
          <Form.Item label='场站图片' required>
            <Form.Item
              name='imgs' noStyle rules={[{required: true, message: '请上传场站图片'}]} 
              valuePropName="fileList" getValueFromEvent={normFile}
            >
              <Upload 
                action="/app/user/fileUp" listType="picture-card"
                data={{type: 1}} maxCount={8}
                headers={{Authorization: localStorage.Authorization}}
                onChange={({file}) => onFileUpLoadChange(file)}
                onPreview={openPreview}
              >
                {
                  !imageList || imageList.length < 8 ? <button style={{ border: 0, background: 'none' }} type="button">
                    <PlusOutlined />
                    <div style={{ marginTop: 8 }}>选择照片</div>
                  </button> : null
                }
              </Upload>
            </Form.Item>
            <div>
              提示：上传图片体积不超过2M，最多可上传8张图片
            </div>
          </Form.Item>
          <Form.Item name='stationName' label='场站名称' rules={[{required: true, message: '请输入场站名称'}]}>
            <Input placeholder='请输入' style={{width: 320}} />
          </Form.Item>
          <Form.Item name='houseName' label='小区名称' rules={[{required: true, message: '请输入小区名称'}]}>
            <Input placeholder='请输入' style={{width: 320}} />
          </Form.Item>
          <Form.Item name='placeArea' label='场地面积' rules={[{required: true, message: '请输入场地面积'}]}>
            <InputNumber placeholder='请输入' precision={2} min={0} style={{width: 320}} controls={false} addonAfter='m²' />
          </Form.Item>
          <Form.Item name='stubOneNum' label='直流数量' rules={[{required: true, message: '请输入直流数量'}]}>
            <InputNumber placeholder='请输入' precision={0} min={0} style={{width: 320}} controls={false} addonAfter='个' />
          </Form.Item>
          <Form.Item name='stubTwoNum' label='交流数量' rules={[{required: true, message: '请输入交流数量'}]}>
            <InputNumber placeholder='请输入' precision={0} min={0} style={{width: 320}} controls={false} addonAfter='个' />
          </Form.Item>
          <Form.Item name='chargeNum' label='充电车位数量' rules={[{required: true, message: '请输入充电车位数量'}]}>
            <InputNumber placeholder='请输入' precision={0} min={0} style={{width: 320}} controls={false} addonAfter='个' />
          </Form.Item>
          <Form.Item name='infoMoney' label='投资金额' rules={[{required: true, message: '请输入投资金额'}]}>
            <InputNumber placeholder='请输入' precision={0} min={0} style={{width: 320}} controls={false} addonAfter='元' />
          </Form.Item>
          <Form.Item name='scale' label='分成比例' rules={[{required: true, message: '请输入分成比例'}]}>
            <InputNumber placeholder='请输入' precision={2} min={0} style={{width: 320}} controls={false} addonAfter='%' />
          </Form.Item>
          <Form.Item name='hzqx' label='合作期限' rules={[{required: true, message: '请选择合作期限'}]}>
            <Input placeholder='请输入' style={{width: 320}} />
          </Form.Item>
          <Form.Item name='status' label='场站状态' rules={[{required: true, message: '请选择场站状态'}]}>
            <Radio.Group options={enum2options(ZhaoMuStatus)} />
          </Form.Item>
          <Form.Item name='powerStatus' label='电表状态' rules={[{required: true, message: '请选择电表状态'}]}>
            <Radio.Group options={enum2options(PowerStatus)} />
          </Form.Item>
          <Form.Item name='lockStatus' label='地锁状态' rules={[{required: true, message: '请选择地锁状态'}]}>
            <Radio.Group options={enum2options(LockStatus)} />
          </Form.Item>
          <Form.Item label='场站介绍' required>
            <div style={{border:'1px solid #f0f0f0',borderRadius:10,overflow:'hidden',width:720}}>
              <Toolbar
                editor={editor}
                defaultConfig={toolbarConfig}
                mode="default"
                style={{ borderBottom: '1px solid #ccc' }}
              />
              <Editor
                defaultConfig={editorConfig}
                onCreated={setEditor}
                mode="default"
                value={disposeRes}
                onChange={(editor: any) => setDisposeRes(editor.getHtml())}
                style={{ height: '300px', overflowY: 'hidden' }}
              />
            </div>
          </Form.Item>
          <Form.Item name='cascader' label='所在城市' rules={[{required: true, message: '请选择所在城市'}]}>
            <Cascader
              loading={cityOptions.loading}
              options={cityOptions.data?.data}
              style={{width: 320}}
              placeholder='请选择'
              onChange={onCityChange}
            />
          </Form.Item>
          <Form.Item label=' ' colon={false}>
            <LatLngContainer>
              <Input style={{width: 390}} placeholder='请输入要搜索的地址' onChange={({target}) => keyword.current = target.value} />
              <Button type='primary' style={{marginLeft: 16}} onClick={onSearch} loading={tencentReq.loading}>查询</Button>
            </LatLngContainer>
          </Form.Item>
          <Form.Item label=' ' colon={false}>
            <MapContainer>
              <div id='mapContainerZm' className="map-content"></div>
              <Access accessible={addressList.length > 0}>
                <div className="map-list">
                  {
                    addressList.map((it, idx) => <div className='map-item' key={idx} onClick={() => onAddressChose(it)}>
                      {it.address}
                    </div>)
                  }
                </div>
              </Access>
            </MapContainer>
          </Form.Item>
          <Form.Item label='经度' required>
            <LatLngContainer>
              <Form.Item name='longitude' rules={[{required: true, message: '请选择经纬度'}]} noStyle>
                <Input placeholder='请输入' style={{width: 200}} />
              </Form.Item>
              <div className='label'>纬度</div>
              <Form.Item name='latitude' noStyle>
                <Input placeholder='请输入' style={{width: 200}} />
              </Form.Item>
            </LatLngContainer>
          </Form.Item>
          <Form.Item name='address' label='场站地址' rules={[{required: true, message: '请输入场站地址'}]}>
            <Input placeholder='请输入' style={{width: 320}} />
          </Form.Item>
          <Form.Item name='serviceInfo' label='营业时间' required>
            <OpeningHours />
          </Form.Item>
          <Form.Item name='parkType' label='停车费' rules={[{required: true, message: '请选择停车收费类型'}]}>
            <Radio.Group options={enum2options(StationParkType)} />
          </Form.Item>
          <Form.Item label=' ' colon={false} name='parkInfo' required={false} rules={[{required: true, message: '请输入停车费介绍'}]}>
            <Input placeholder='示例: 2小时内停车免费' style={{width: 320}} />
          </Form.Item>
          <Form.Item name='linkInfo' label='联系方式' rules={[{validator: (_, val) => managerInfoValidator(val)}]}>
            <ManagerInfo />
          </Form.Item>
          <Form.Item label=' ' colon={false}>
            <Button type='primary' htmlType='submit' loading={loading}>提交</Button>
          </Form.Item>
        </Form>
      </div>
      <Image.PreviewGroup
        items={imgList}
        preview={{
          visible: imgList.length > 0,
          current: previewCurrent,
          onChange: (val) => {
            setPreviewCurrent(val)
          },
          onVisibleChange: (val) => {
            if (!val) setImgList([])
          }
        }}
      >
      </Image.PreviewGroup>
    </div>
  );
};

export default RoleEditPage;
